<?php
namespace app\taobao\command;

use app\common\model\FilterWord;
use app\common\model\ItemWare;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use app\common\model\ItemWare as ItemWareModel;
use app\common\model\User as UserModel;
use app\common\model\FilterWord as FilterWordModel;
use \Redis;

use Curl\Curl;
use taobao\top\request\ItemImgUploadRequest;
use taobao\top\request\ItemUpdateRequest;
use taobao\top\TopClient;
use taobao\top\request\ItemAddRequest;
use taobao\top\request\ItempropsGetRequest;
use taobao\top\request\ItemcatsGetRequest;
use taobao\top\request\ItempropvaluesGetRequest;
use taobao\top\request\ItemPropimgUploadRequest;
use taobao\top\request\PictureUploadRequest;
use taobao\top\request\ItemJointPropimgRequest;
use taobao\top\request\ItemSkuUpdateRequest;
use taobao\top\request\ItemSellerGetRequest;
use think\image\Exception;


/**
 * 单个上传任务
 * class Task
 * @package app\taobao\command
 */
class Task extends Command{


    protected $appKey = '';

    protected $appSecret = '';

    protected $topClient = null;

    protected $resp = null;

    protected $loginSession = '';

    protected $itemUrl = 'https://item.taobao.com/item.htm?spm=a1z10.1-c.w5003-15459902196.4.213f10e6twNyUx&id=542051820668&scene=taobao_shop';

    protected $rootPath = 'E:\money\caiji\python\dev';

    protected $itemId = '';

    protected $spiderResult = '';

    /**
     * 所以过滤都是在python当中过滤了 php 就不参与过滤了
     * 用户采集淘宝的基本配置参数
     *   'price' => [0=>['percent'=>100,'increment'=>''],100=>['percent'=>100,'increment'=>1],...]   价格设置
     *   'keep_origin_url'=>'1'   是否保留原来的链接 隐藏链接设置
     *   'filter_sys_brand'=>'1'  标题是否过滤系统品牌库中的品牌
     *   'filter_sys_title'=>'1'  标题是否过滤系统禁用关键词
     *   'modify_brand' => '1'    属性中的品牌是否改成其他
     * @var string
     */
    protected $userTaobaoConfig = '';

    /**
     * 价格处理策略  默认不加价
     * @var null
     */
    protected $priceConfig = ['percent'=>100,'increment'=>0];


    /**
     * 队列中取出来的数据
     * @var null
     */
    protected $finishedTask = null;


    protected function configure(){
        $this->setName('task')->setDescription("do the job to upload a item to taobao");
    }


    public function init()
    {

        if (!defined("TOP_SDK_WORK_DIR"))
        {
            define("TOP_SDK_WORK_DIR", EXTEND_PATH."taobao\\log\\");
        }

        /**
         * 是否处于开发模式
         * 在你自己电脑上开发程序的时候千万不要设为false，以免缓存造成你的代码修改了不生效
         * 部署到生产环境正式运营后，如果性能压力大，可以把此常量设定为false，能提高运行速度（对应的代价就是你下次升级程序时要清一下缓存）
         */
        if (!defined("TOP_SDK_DEV_MODE"))
        {
            define("TOP_SDK_DEV_MODE", true);
        }

        $taobaoConfig = Config("taobao");
        $this->appKey = $taobaoConfig['appKey'];
        $this->appSecret = $taobaoConfig['appSecret'];
        $this->rootPath = $taobaoConfig['rootPath'];

        $this->topClient = new TopClient();
        $this->topClient->appkey = $this->appKey;
        $this->topClient->secretKey = $this->appSecret;

    }



    //-------------------------------------------------接口测试-------------------------------------------------------------------

    /**
     * 获取某个类目下的所有可以用的属性和属性值 但是有一点非常奇怪就是名字跟淘宝页面上的名字对不上 虽然id对得上 名字只是大致对的上 也许淘宝偷偷的显示的时候稍微更换了个名字 这样防止被盗
     */
    private function apiItemPropValuesGet(){
        $req = new ItempropvaluesGetRequest();
        $req->setFields("cid,pid,prop_name,vid,name,name_alias,status,sort_order");
        $req->setCid("203509");
        //$req->setPvs("20561:1234");
        //$req->setDatetime("2017-01-01 00:00:00");
        $req->setType("1");
        $resp = $this->topClient->execute($req);
        $res = var_export($resp,true);
        file_put_contents('proper2.txt',$res);
        echo 'a';
    }

    private function ItemcatsGetRequest(){
        $req = new ItemcatsGetRequest;
        $req->setCids("50011999");
        #$req->setDatetime("2000-01-01 00:00:00");
        $req->setFields("cid,parent_cid,name,is_parent");
        #$req->setParentCid("50011999");
        $resp = $this->topClient->execute($req);
        var_dump($resp);
    }

    public function apiItemSellerGetRequest(){
        $req = new ItemSellerGetRequest();
        $req->setFields("num_iid,title,nick,price,approve_status,sku");
        $req->setNumIid("557054961886");
        $resp = $this->topClient->execute($req, '62029241cff2559ac81be9fd829a9a1bdfc4204b7f46b7c314210378');
        var_dump($resp);
    }



    //------------------------------------------接口测试----------------------------------------------------------------------------





























    protected function execute(Input $input,Output $output ){
        /*$redis = new Redis();
        $redis -> connect('localhost');
        $this->spiderResult = $redis->hGet('resultDict','');
        $basicInfo = $this->getItemBasicInfo();
        $parsedInfo = $this->parseBasicInfo($basicInfo);
        var_dump($parsedInfo);*/
        set_time_limit(0);
        ini_set('default_socket_timeout',315360000);//设置过期时间十年 这样约等于永久了吧
        $this->init();
        $taobaoConfig = Config('taobao');
        $finishQueue = $taobaoConfig['finishQueue'];
        $controlQueue = $taobaoConfig['controlQueue'];
        $resultDict = $taobaoConfig['resultDict'];
        $redis = new Redis();
        $redis->connect('localhost');
        try {


            $finishedTask = $redis->brpop($finishQueue,0);
            $finishedTask = $finishedTask[1];
            $finishedTask = json_decode($finishedTask, true);
            $this->finishedTask = $finishedTask;
            $this->itemId = $finishedTask['itemId'];

	        var_dump($finishedTask);
            //先查看是否采集出错 出错记录 完事
            if ($finishedTask['errCode'] == 1) {
                ItemWareModel::update(['status' => 3, 'process_msg' => $finishedTask['errMsg']], ['id' => $finishedTask['itemwareid']]);
                $redis->hDel($resultDict, $this->itemId);
                $this->delItem($this->itemId);
                $redis->lpush($controlQueue, $this->itemId);
                exit;
            }

            //从数据库中拿好了
            $userId = $finishedTask['userid'];
            $userInfo = UserModel::find($userId);
            $this->loginSession = $userInfo->taobaosession;
            $this->userTaobaoConfig = $userInfo->taobao_config;
            $this->userTaobaoConfig = json_decode($this->userTaobaoConfig);//一些上传的小配置  其实很多配置只要保存一个user_id 就可以娶到了 到时候看看用什么办法吧

            $this->parseUserTaobaoConfig();


            $this->spiderResult = $redis->hGet($resultDict, $this->itemId);

            if (!$this->spiderResult) {
                ItemWareModel::update(['status' => 3, 'process_msg' => '没有采集到信息'], ['id' => $finishedTask['itemwareid']]);
                exit;
            }
            try {
                $res = $this->spiderItem();
            } catch (\Exception $e) {
                //ItemWareModel::update(['status' => 3, 'process_msg' => $e->getMessage().';line:'.$e->getLine().':trace:'.$e->getTraceAsString()], ['id' => $finishedTask['itemwareid']]);
                ItemWareModel::update(['status' => 3, 'process_msg' => $e->getMessage()], ['id' => $finishedTask['itemwareid']]);
                $redis->lpush($controlQueue, $this->itemId);
                //删除字典中的信息 和相关的图片 以及数据  更新数据库中的状态
                $redis->hDel($resultDict, $this->itemId);
                $this->delItem($this->itemId);
		        throw new \Exception('error down');
            }

            $redis->lpush($controlQueue, $this->itemId);
            //删除字典中的信息 和相关的图片 以及数据  更新数据库中的状态
            $redis->hDel($resultDict, $this->itemId);
            $this->delItem($this->itemId);
            ItemWareModel::update(['status' => 2, 'process_msg' =>''], ['id' => $finishedTask['itemwareid']]);
        }catch (\Exception $e){

            var_dump($e->getMessage());
            $redis->lpush($controlQueue,$e->getMessage());
        }


    }

    /**
     * 主要处理价格策略
     */
    private function parseUserTaobaoConfig(){
        //处理加价信息
        //price 结构 [0=>['percent'=>100,'increment'=>''],100=>['percent'=>100,'increment'=>1],...]
        if(isset($this->userTaobaoConfig['price'])){
            $maxKey = 0;
            foreach($this->userTaobaoConfig['price'] as $key => $val ){
                if(intval($key) > $maxKey){
                    $maxKey = $key;
                }
            }
            if(isset($this->userTaobaoConfig['price'][$maxKey])){
                $this->priceConfig = $this->userTaobaoConfig['price'][$maxKey];
            }
        }
    }


    private function delItem($itemId){
        $path = $this->rootPath.DS.'csv'.DS.'taobaoPack'.$itemId;
        $this->delPath($path);
        $path = $this->rootPath.DS.'goods'.DS.$itemId;
        $this->delPath($path);
    }

    private function delPath($path){
        $op = dir($path);
        while(false != ($item = $op->read())) {
            if($item == '.' || $item == '..') {
                continue;
            }
            if(is_dir($op->path.'/'.$item)) {
                $this->delPath($op->path.'/'.$item);
                rmdir($op->path.'/'.$item);
            } else {
                unlink($op->path.'/'.$item);
            }

        }

    }


    private function getItemBasicInfo(){
        $res = preg_match_all('/"([^"]*)"=>"([^"]*)"/',$this->spiderResult,$match);
        if($res){
            $basicInfo = array_combine($match[1],$match[2]);
        }else{
            return [];
        }

        return $basicInfo;
    }

    private function getDescImg($itemId){
        $path = $this->rootPath.DS.'csv'.DS.'taobaoPack'.$itemId.DS.'media';
        $dir = opendir($path);
        $imageList = [];
        while($fileName = readdir($dir)){
            if($fileName !== '.' && $fileName !== '..'){
                array_push($imageList,$path.DS.$fileName);
            }
        }
        return $imageList;
    }

    private function getMajor($itemId){
        $path = $this->rootPath.DS.'csv'.DS.'taobaoPack'.$itemId;
        $dir = opendir($path);
        $imageList = [];
        while($fileName = readdir($dir)){
            if(strpos($fileName,'zhutu') !== false){
                array_push($imageList,$path.DS.$fileName);
            }
        }
        return $imageList;
    }

    //获取属性图片
    private function getPropsImage($itemId,$colorInfo){
        $path = $this->rootPath.DS.'csv'.DS.'taobaoPack'.$itemId;

        foreach($colorInfo as $key => $val ){
            $colorInfo[$key]['path'] = $path.DS.$val[0].'.jpg';
        }

        return $colorInfo;
    }


    private function parseBasicInfo($basicInfo){
        $picture = $basicInfo['picture'];
        $pictureInfo = explode('|',$picture);
        $pictureGroup = ['zhutu'=>[],'color'=>[]];
        foreach($pictureInfo as $key => $val ){
            if(strpos($val,'zhutu') !== false){
                array_push($pictureGroup['zhutu'],$val);
            }else if(strpos($val,'color') !== false){
                array_push($pictureGroup['color'],$val);
            }
        }

        $zhutu = [];
        foreach($pictureGroup['zhutu'] as $val){
            $val = trim($val,";");
            $result = explode(":",$val);
            array_push($zhutu,$result);
        }

        $color = [];
        foreach($pictureGroup['color'] as $val){
            $val = trim($val,";");
            $result = explode(":",$val);
            array_push($color,$result);
        }

        $parsedInfo['zhutu'] = $zhutu;
        $parsedInfo["color"] = $color;

        return $parsedInfo;
    }

    /**
     * 对采集到的信息 进行一些加工 主要针对用户的配置   过滤的在python那边处理 这边只负责去除关键词 目前这个去除功能没有 配置的键以后也要换
     * @param $basicInfo
     */
    private function processBasicInfo($basicInfo){
        //标题处理
        /*$command = '';
        if(isset($this->userTaobaoConfig['filter_sys_brand']) && $this->userTaobaoConfig['filter_sys_brand']){
            //获取词库 这里干脆调用python程序来处理
            //过滤的命令  python filterwords.py --title=商品的标题 --type=brand  --type=stopword
            $command = 'export LANG="en_US.UTF-8";python3 ../work/filterwords.py --title="'.$basicInfo['title'].'" --type=brand';
        }
        if(isset($this->userTaobaoConfig['filter_sys_title']) && $this->userTaobaoConfig['filter_sys_title']){
            $command .= '  --type=stopword';
        }
        //必要时要对命令进行转码
        if($command){
            $res = shell_exec($command);
            if($res) $basicInfo['title'] = $res;
        }*/

        //价格处理
        $basicInfo['price'] = (floatval($this->priceConfig['percent']) / 100 ) * floatval($basicInfo['price']) + floatval($this->priceConfig['increment']);
        $basicInfo['price'] = strval($basicInfo['price']);
        return $basicInfo;
    }

    /**
     * 采集一个商品到店铺
     */
    private function spiderItem(){

        $basicInfo = $this->getItemBasicInfo();
        $parsedInfo = $this->parseBasicInfo($basicInfo);

        //处理商品信息
        $basicInfo = $this->processBasicInfo($basicInfo);

        if(!isset($basicInfo['skuProps'])){
            $skuProps = '';
        }else{
            $skuProps = $basicInfo['skuProps'];
        }

        $numIId = $this->itemAdd($basicInfo);


        //json_encode之后是这样的 '{"0":"556578063083"}' 不知道是什么原因
        $tmp = json_decode(json_encode($numIId),true);
        $numIId = $tmp[0];

        //$numIId = '556475557855';
        //上传详情描述中的图片    这些图片都在图片空见 通过itemimgupload的上传的最多5张 是在左上角的图片  主图是第一张图 所以主图只有一张
        $descImages = $this->getDescImg($this->itemId);

        $imageArr = $this->pictureUpload($descImages);


        //更新描述
        $this->itemUpdate($numIId,$imageArr);

        //一直理解错误 主图其实就是第一张  其他的都不是
        //上传主图
        //获取主图
        $mainImages = $this->getMajor($this->itemId);

        $this->itemImgUpload($numIId,$mainImages);

        //上传属性图片
        //获取属性图片
        $propsImages = $this->getPropsImage($this->itemId,$parsedInfo['color']);
        //分析基础信息 获取图片信息 区分主图和属性图
        $this->itemPropimgUpload($numIId,$propsImages);

        $this->apiItemSkuUpdate($numIId,$skuProps);
        //完工
        return true;
    }

    private function apiItemSkuUpdate($numIId,$skuProps){
        if(!$skuProps) return;
        $req = new ItemSkuUpdateRequest();
         //12.8:200::1627207:28332;12.8:200::1627207:13434;1627207:28332
        $item = explode(';',trim($skuProps,';'));
        foreach($item as $key => $val ){
            $item[$key] = explode(':',$val);
        }
        $groupItem = [];
        $index = 0;
        foreach($item as $key => $val ){

            if(count($val) == 5){
                $index++;//表示新起一行

                if(!isset($groupItem[$index]['skus'])){
                    $groupItem[$index]['skus'] = [];
                }

                $groupItem[$index]['price'] = [$val[0],$val[1]];
                array_push($groupItem[$index]['skus'],[$val[3],$val[4]]);
            }else{
                array_push($groupItem[$index]['skus'],$val);
            }
        }

        foreach($groupItem as $key => $val ){
            //12.8:200::1627207:28332;167294:43144
            $req->setNumIid($numIId);
            $propertiesKeyValStr = "";
            foreach($val['skus'] as $k => $v){
                $propertiesKeyValStr = $v[0].":".$v[1].';';
            }
            $propertiesKeyValStr = trim($propertiesKeyValStr,';');
            //$req->setProperties($val[0][3].':'.$val[0][4].';'.$val[1][0].':'.$val[1][1]);
            $req->setProperties($propertiesKeyValStr);

            //$req->setQuantity($val[0][1]);
            $req->setQuantity($val['price'][1]);
            $price = $val['price'][0];
            $price  = strval((floatval($this->priceConfig['percent']) / 100 ) * floatval($price) + floatval($this->priceConfig['increment']));
            $req->setPrice($price);

            $resp = $this->topClient->execute($req, $this->loginSession);
            if(isset($resp->sub_msg)){
                throw new \Exception($resp->sub_msg);
            }
            var_dump($resp);
        }
    }


    private function itemPropimgUpload($itemIid,$propsImages){
        foreach($propsImages as $key => $val ){
            $req = new ItemPropimgUploadRequest();
            $req->setNumIid($itemIid);
            $req->setProperties($val[3].":".$val[4]);
            $req->setImage('@'.$val['path']);
            $resp = $this->topClient->execute($req, $this->loginSession);
        }

    }


    /**
     * 添加一个商品 先要上传商品的图片 才能在
     * @param $param
     */
    private function itemAdd($basicInfo)
    {
        $param = $basicInfo;

        $req = new ItemAddRequest();
        $req->setNum($param['num']);
        $req->setPrice($param['price']);
        $req->setType("fixed");
        $req->setStuffStatus("new");
        $req->setTitle($param['title']);
        $req->setDesc($param['description']);//详情 初始的description保存采集的商品的地址
        $req->setLocationState($param["location_state"]);
        $req->setLocationCity($param['location_city']);
        $req->setApproveStatus("onsale");
        $req->setCid($param['cid']);
        $req->setProps($param['cateProps']);
        $req->setPropertyAlias($param['propAlias']);
        //$req->setWirelessDesc($param["wireless_desc"]);//无线详情
        //$req->setSkuProperties($param['skuProps']);
        $this->resp = $this->topClient->execute($req, $this->loginSession);
        if(isset($this->resp->item->iid)){
            return $this->resp->item->iid;
        }else{
            if(isset($this->resp->sub_msg)){
                throw new \Exception($this->resp->sub_msg);
            }else if(isset($this->resp->msg)){
                throw new \Exception($this->resp->msg);
            }else{
                throw new \Exception('上传商品基本信息失败');
            }

        }
    }


    /**
     * 这里的图片上传完毕就行 不用返回 因为上传了 就会自动到左上角 所以后面的返回暂时没有什么用
     * @param $numIId
     * @param $pathArr
     * @param string $major
     * @return array
     */
    private function itemImgUpload($numIId, $pathArr,$major="false"){
        $imageUrlArr = [];
        foreach($pathArr as $key => $val ){
            if($key > 4) continue; //最多5张图
            $req = new ItemImgUploadRequest();
            //$req->setPosition($key+1);
            $req->setNumIid($numIId);
            $req->setImage('@'.$val);
            if($key == 0){
                $major = "true"; //加上这个图才允许5张 除掉这个 只能传四张
            }else{
                $major = "false";
            }
            $req->setIsMajor($major);
            $this->resp = $this->topClient->execute($req, $this->loginSession);
            if(isset($this->resp->item_img->url)){
                array_push($imageUrlArr,$this->resp->item_img->url);
            }
        }
        return $imageUrlArr;
    }

    //描述里的图片都要从这里上传
    private function pictureUpload($pictureArr){
        $urlArr = [];
        foreach($pictureArr as $key => $val ){
            $req = new PictureUploadRequest();
            $req->setPictureCategoryId("0");
            $req->setImg('@'.$val);
            $req->setImageInputTitle(basename($val));
            $resp = $this->topClient->execute($req, $this->loginSession);
            if(isset($resp->picture->picture_path)){
                array_push($urlArr,$resp->picture->picture_path);
            }
        }
        return $urlArr;
    }







    private function itemUpdate($numIId,$imageArr){
        $req = new ItemUpdateRequest();
        $req->setNumIid($numIId);

        //$desc = '';
        //if($this->userTaobaoConfig['keep_origin_url']){
            $desc = '<a style="color: white;" href="'.$this->finishedTask['url'].'" target="_blank" >******</a>';
        //}

        foreach($imageArr as $key => $val ){
            $desc .= "<img src='".$val."'>";
        }
        $req->setDesc($desc);
        $this->resp = $this->topClient->execute($req, $this->loginSession);
    }

}






